package com.m1.tzolkin.model.board;

import java.io.Serializable;
import java.util.Collection;
import java.util.Map;

import com.m1.tzolkin.model.IAction;
import com.m1.tzolkin.model.ITZStock;
import com.m1.tzolkin.model.TZResource;
import com.m1.tzolkin.model.exceptions.NoAvailableSkullException;
import com.m1.tzolkin.model.exceptions.NotAvailableActionException;
import com.m1.tzolkin.model.exceptions.NotEnoughCornException;
import com.m1.tzolkin.model.exceptions.NotEnoughResourceException;
import com.m1.tzolkin.model.exceptions.StepMoveException;
import com.m1.tzolkin.model.exceptions.WaitingOperationsException;
import com.m1.tzolkin.model.players.ITZPlayer;
import com.m1.tzolkin.model.technos.ITechnology;
import com.m1.tzolkin.model.technos.ITechnology.TechLevel;
import com.m1.tzolkin.model.temples.ITemple;

/**
 * Un plateau permettant de payer des choses (technologies/constructibles).
 *
 */
public interface ITZBoard extends ITechBoard, Serializable {
	
	// REQUETES
	
	/**
	 * Retourne l'ensemble des technologies du joueur p.
	 */
	Collection<TechLevel> getTechnologies(ITZPlayer p);
	
	/**
	 * Retourne le niveau technologique selon l'ordre de l'enum.
	 */
	int getTechLevel(ITechnology t, ITZPlayer p);
	
	/**
	 * Retourne l'ensemble des actions possibles.
	 */
	Map<IAction, Integer> getActions();
	
	/**
	 * Retourne la somme que le joueur courant doit payer.
	 */
	ITZStock mustPay();
	
	/**
	 * Retourne la quantit� de ressources/cr�nes que le joueur courant peut �conomiser.
	 */
	int canSave();
	
	/**
	 * Retourne true si le joueur doit payer ses constructions en ma�s.
	 */
	boolean mustPayInCorn();
	
	/**
	 * Retourne le nombre d'unit�s de ressource quelconque que le joueur doit payer.
	 */
	int randomToPay();
	
	/**
	 * Retourne true si le joueur p peut monter d'une marche dans le temple t.
	 */
	boolean canUpTemple(ITemple t, ITZPlayer p);
	
	/**
	 * Retourne true si le joueur p peut descendre d'une marche dans le temple t.
	 */
	boolean canDownTemple(ITemple t, ITZPlayer p);
	
	// COMMANDES
	
	/**
	 * Monte le joueur p dans la technologie t.
	 * Ajoute des actions en fonction de la derni�re marche.
	 * @pre <pre>
	 *     canUpTechs() > 0
	 *     p != null
	 *     t != null </pre>
	 * @post <pre>
	 *     canUpTechs() == old canUpTechs() - 1
	 */
	void upTech(ITechnology t, ITZPlayer p);
	
	/**
	 * Active l'action a en payant l'�ventuel co�t de reculade.
	 * @pre <pre>
	 *     isWaitingForTurn() == 0
	 *     a != null
	 *     getActions().contains(a) </pre>
	 */
	void doAction(IAction a) throws NoAvailableSkullException, NotEnoughCornException, NotAvailableActionException, WaitingOperationsException;
	
	/**
	 * Donne au joueur courant les actions qu'il peut r�aliser.
	 * Fait le tri en fonction du ma�s disponible pour le prix d'ex�cution.
	 * @pre <pre>
	 *     isWaitingForTurn() == 0
	 *     actions != null </pre>
	 * @post <pre>
	 *     les actions actuellement stock�es sont remplac�es par actions </pre>
	 */
	void setActions(Map<IAction, Integer> act);
	
	/**
	 * Demande � monter dans la technologie t moyennant son co�t en ressources.
	 * Retourne le co�t en ressources.
	 */
	int wannaUpTech(ITechnology t) throws NotEnoughResourceException, NotAvailableActionException;
	
	/**
	 * Demande � monter dans le temple t moyennant n ressources.
	 */
	void wannaUpTemple(ITemple t) throws NotEnoughResourceException, StepMoveException, NotAvailableActionException;
	
	/**
	 * Paie une unit� de la ressource r.
	 * @pre <pre>
	 *     r != null </pre>
	 */
	public void pay(TZResource r);
	
	/**
	 * Force � choisir qty de ressources quelconques.
	 * @pre <pre>
	 *     qty >= 0 </pre>
	 */
	public void setToPay(int qty);
	
	/**
	 * Force � payer ses b�timents en ma�s.
	 */
	void setPayInCorn(boolean must);
	
	/**
	 * Economise une unit� de la ressource r.
	 */
	void save(TZResource r);
	
	/**
	 * Economise un cr�ne.
	 */
	void saveSkull();

}
